/**
 * Copyright 2011 Honeywell Federal Manufacturing & Technologies, LLC. This material was produced under U.S. Government
 * contract DE-ACO4-01AL66850, Honeywell Federal Manufacturing & Technologies, LLC, (FM&T) with the U. S. Department of
 * Energy for the operation of the Kansas City Plant . The U.S. Government has rights to use, reproduce, and distribute
 * this software.  NEITHER THE GOVERNMENT NOR Honeywell Federal Manufacturing & Technologies, LLC, MAKES ANY WARRANTY,
 * EXPRESS OR IMPLIED, OR ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified to produce
 * derivative works, such modified software should be clearly marked, so as not to confuse it with the version available
 * from FM&T.
 *
 * Additionally, this program is free software; you can redistribute it and/or modify it under the terms of the GNU
 * General Public License Version 3 published by the Free Software Foundation. Accordingly, this program is distributed in
 * the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this library.
 * If not, see http://www.gnu.org/licenses/.
 */
package org.braintrain.services;

import com.kcp.ko.authentication.domain.AuthenticatableUser;
import org.apache.log4j.Logger;
import org.apache.tapestry.util.exception.ExceptionDescription;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.ui.velocity.VelocityEngineUtils;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Message service implementation 
 * @author Robert Engelhardt
 *
 */
public class MessageServiceImpl implements MessageService, InitializingBean {

	private static final String ERROR_MESSGE_TEMPLATE = "errorMessage.vm";
	
	private static final Logger LOG = Logger.getLogger(MessageServiceImpl.class);
	
	private JavaMailSender mailSender;
	private String errorMailReceiver;
	private String errorMailSender;
	private boolean sendMailOnError;
	private VelocityEngine velocityEngine;
	
	/**
	 * Construct a new message service
	 */
	public MessageServiceImpl() {
		// this constructor purposely left blank
	}

    /**
	 * @return the mailSender
	 */
	public JavaMailSender getMailSender() {
		return mailSender;
	}
	/**
	 * @param mailSender the mailSender to set
	 */
	public void setMailSender(JavaMailSender mailSender) {
		this.mailSender = mailSender;
	}
	
	/**
	 * Send a message to a recipient
	 * 
	 * @param recipient the email address of the recipient, assumes valid address
	 * @param originator the mail sender
	 * @param messageSubject the subject of the message
	 * @param messageBody the body of the message to be sent to the recipient
	 * @param attachmentFileName the file name of the attachment 
	 * @param attachment the attachment to include with the message, null for no attachment
	 * 
	 * @throws MailException
	 * @throws MessagingException 
	 */
	public void sendMessage( AuthenticatableUser recipient, String originator, String messageSubject, String messageBody, String attachmentFileName, byte[] attachment ) throws MailException, MessagingException {

        if(recipient.getProfile().getEmail() != null){

            MimeMessage message = getMailSender().createMimeMessage();
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message, true);
            mimeMessageHelper.setTo( recipient.getProfile().getEmail() );
            mimeMessageHelper.setFrom( originator );
            mimeMessageHelper.setSubject(messageSubject);
            mimeMessageHelper.setText(messageBody, true);

            if( attachment != null ) {	// set an attachment if one exists
                mimeMessageHelper.addAttachment(attachmentFileName, new ByteArrayResource(attachment) );
            }

            getMailSender().send(message);
        }
        else{
            LOG.error("empty email address for user " + recipient.getProfile().getId());
        }
	}

	/**
	 * Send an exception message
	 * 
	 * @param exceptions the exception encountered
	 * @param userName the user that encountered the message
	 * @throws Exception 
	 */
	public void sendException( ExceptionDescription[] exceptions, String userName) throws Exception {
		
		if( sendMailOnError ) {
		
			MimeMessage message = getMailSender().createMimeMessage();
			MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message, true);
			mimeMessageHelper.setTo( getErrorMailReceiver()  );
			mimeMessageHelper.setFrom( getErrorMailSender() );
			mimeMessageHelper.setSubject( "BrainTrain: an error has occured ");

			Map<String,Object> model = new HashMap<String, Object>();
			if( userName != null ) {
				model.put("user", userName );
			}
            
           
			model.put("date", new Date() );
			model.put("exceptions", exceptions);
			
			String messageBody = VelocityEngineUtils.mergeTemplateIntoString( getVelocityEngine(), ERROR_MESSGE_TEMPLATE, model);
			
			mimeMessageHelper.setText( messageBody, true );
            
			
			getMailSender().send(message);
		
		}
	}
	
	public void afterPropertiesSet() throws Exception {
		if(getMailSender() != null)
		{
		    setSendMailOnError(! (getErrorMailReceiver() == null || getErrorMailReceiver().trim().equals("") || getErrorMailSender() == null || getErrorMailSender().trim().equals("")) );
		}
		else
		{
		    LOG.warn("Mail Sending Not Specified");
		}
	}

	/**
	 * @return the errorMailReceiver
	 */
	public String getErrorMailReceiver() {
		return errorMailReceiver;
	}

	/**
	 * @param errorMailReceiver the errorMailReceiver to set
	 */
	public void setErrorMailReceiver(String errorMailReceiver) {
		this.errorMailReceiver = errorMailReceiver;
	}

	/**
	 * @return the errorMailSender
	 */
	public String getErrorMailSender() {
		return errorMailSender;
	}

	/**
	 * @param errorMailSender the errorMailSender to set
	 */
	public void setErrorMailSender(String errorMailSender) {
		this.errorMailSender = errorMailSender;
	}

	/**
	 * @return the sendMailOnError
	 */
	public boolean isSendMailOnError() {
		return sendMailOnError;
	}

	/**
	 * @param sendMailOnError the sendMailOnError to set
	 */
	public void setSendMailOnError(boolean sendMailOnError) {
		this.sendMailOnError = sendMailOnError;
	}

	/**
	 * @return the velocityEngine
	 */
	public VelocityEngine getVelocityEngine() {
		return velocityEngine;
	}

	/**
	 * @param velocityEngine the velocityEngine to set
	 */
	public void setVelocityEngine(VelocityEngine velocityEngine) {
		this.velocityEngine = velocityEngine;
	}

}
